package com.web.oa.service.impl;

import com.web.oa.mapper.BaoxiaoBillMapper;
import com.web.oa.pojo.ActiveUser;
import com.web.oa.pojo.BaoxiaoBill;
import com.web.oa.service.WorkFlowService;
import com.web.oa.utils.Constants;
import org.activiti.cdi.annotation.TaskId;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;
@Service
public class WorkFlowServiceImpl implements WorkFlowService {
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private BaoxiaoBillMapper baoxiaoBillMapper;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private HistoryService historyService;


    /**部署流程*/
    @Override
    public void addFlowProcess(InputStream fileName, String processName) {
        ZipInputStream zis=new ZipInputStream(fileName);
        this.repositoryService.createDeployment()
                .name(processName)
                .addZipInputStream(zis)
                .deploy();
    }

    /**设置待办任务*/
    @Override
    public List<Task> findMyTaskList(String username) {
        List<Task> list=this.taskService.createTaskQuery()
                .taskAssignee(username).orderByTaskCreateTime().desc().list();
        return list;
    }



    /**保存报销单数据到数据库中*/
    @Override
    public void saveBaoxiaoBill(BaoxiaoBill baoxiaoBill) {
        Long id=baoxiaoBill.getId();
        if(id==null){
            this.baoxiaoBillMapper.insert(baoxiaoBill);
        }else {
            baoxiaoBillMapper.updateByPrimaryKey(baoxiaoBill);
        }
    }

    /**启动报销流程*/
    @Override
    public void startBaoxiaoBill(Long id,  ActiveUser activeUser) {
        //组装bussnessKey
        String bussnessKey=Constants.BAOXIAO_KEY+"."+ id;

        Map<String,Object> map=new HashMap<>();
        map.put("inputUser",activeUser.getUsername());
        map.put("objectId",bussnessKey);

        //this.runtimeService.startProcessInstanceByKey(Constants.LEAVE_KEY,map);
        //Constants.BAOXIAO_KEY是要启动流程定义的key
        //bussnessKey是流程实例的业务key
        //map是启动参数
        this.runtimeService.startProcessInstanceByKey(Constants.BAOXIAO_KEY,bussnessKey,map);
    }


    /**先获取任务ID获取对应的请假单对象*/
    @Override
    public BaoxiaoBill findBaoxiaoBillByTaskId(String taskId) {
        //先根据taskId获取task任务
        Task task = this.taskService.createTaskQuery()
                .taskId(taskId).singleResult();
        //runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult()方法获取与该任务相关联的流程实例对象
        ProcessInstance processInstance = this.runtimeService.createProcessInstanceQuery()
                .processInstanceId(task.getProcessInstanceId())
                .singleResult();
        //流程实例对象中获取业务key是数据库中`act_ru_execution`这一个表中的business_key这一列
        String businessKey = processInstance.getBusinessKey();

        String id="";

        //将key切割为数组,切割后的数组第二个元素即为请假单id
        String[] split = businessKey.split("\\.");

        if(businessKey !=null && !"".equals(businessKey.trim())){
            id=split[1];
        }

        //根据请假单id从数据库中查询请假单对象
        BaoxiaoBill baoxiaoBill = this.baoxiaoBillMapper.selectByPrimaryKey(Long.valueOf(id));
        //返回结果
        return baoxiaoBill;
    }


    /**获取与该任务相关联的历史批注信息列表*/
    @Override
    public List<Comment> findCommentListByTaskId(String taskId) {
        //先根据taskId获取task任务
        Task task = this.taskService.createTaskQuery().taskId(taskId).singleResult();
        //
        String processInstanceId = task.getProcessInstanceId();
        //getProcessInstanceComments()方法查询得到所有对应的审批备注Comment对象列表
        List<Comment> comments = this.taskService.getProcessInstanceComments(processInstanceId);
        return comments;
    }

    /**根据当前任务id查找当前活动完成后连接的所有连线名称列表*/
    @Override
    public List<String> findoutcomeListByTaskId(String taskId) {
        //返回存放连线的名称集合
        List<String> list = new ArrayList<String>();
        //1:使用任务ID，查询任务对象
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        //2：获取流程定义ID
        String processDefinitionId = task.getProcessDefinitionId();
        //3：查询ProcessDefinitionEntiy对象
        ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinitionId);
        //使用任务对象Task获取流程实例ID
        String processInstanceId = task.getProcessInstanceId();
        //使用流程实例ID，查询正在执行的执行对象表，返回流程实例对象
        ProcessInstance processInstance = this.runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId)
                .singleResult();
        //获取当前活动的id
        String activityId = processInstance.getActivityId();
        //4：通过当前活动的id获取当前的活动
        ActivityImpl activity = processDefinitionEntity.findActivity(activityId);
        //5：获取当前活动完成之后连线的名称
        List<PvmTransition> pvmList = activity.getOutgoingTransitions();
        if(pvmList !=null && pvmList.size()>0){
            for (PvmTransition pvmTransition : pvmList) {
                String name = (String) pvmTransition.getProperty("name");
                if (StringUtils.isNotBlank(name)) {
                    list.add(name);
                } else {
                    list.add("默认提交");
                }
            }
        }
        return list;
    }

    @Override
    public void submitTaskId(String taskId, String id, String comment, String outcome, String username) {
        //先根据流程实例taskId获取task任务对象
        Task task = this.taskService.createTaskQuery().taskId((taskId)).singleResult();
        //获取实例ID
        String processInstanceId = task.getProcessInstanceId();
        //添加当前任务的审批人
        Authentication.setAuthenticatedUserId(username);

        //添加备注
        this.taskService.addComment(taskId, processInstanceId, comment);

        Map<String,Object> map=new HashMap<>();
        //判断outcome是否为空或者不等于默认提交
        if(outcome !=null && !outcome.equals("默认提交")){
            map.put("message",outcome);
            //完成该任务
            this.taskService.complete(taskId,map);
        }else{
            //taskId.contains(taskId);
            taskService.complete(taskId);
        }

        //根据taskId查询流程实例
        ProcessInstance processInstance = this.runtimeService.createProcessInstanceQuery()
                .processInstanceId(task.getProcessInstanceId()).singleResult();

        //判断：如果流程结束了,则需要修改一下请假单的状态
        if (processInstance == null) {
            BaoxiaoBill baoxiaoBill = this.baoxiaoBillMapper.selectByPrimaryKey(Long.valueOf(id));
            baoxiaoBill.setState(2);

            baoxiaoBillMapper.updateByPrimaryKey(baoxiaoBill);
        }

    }
    //查询部署流程对象信息
    @Override
    public List<Deployment> findDeploymentList() {
        return repositoryService.createDeploymentQuery().orderByDeploymenTime().asc().list();
    }
    //查询流程定义信息
    @Override
    public List<ProcessDefinition> findProcessDefinitionList() {
        return repositoryService.createProcessDefinitionQuery().orderByProcessDefinitionVersion().asc().list();
    }
    //通过任务ID查询流程定义对象
    @Override
    public ProcessDefinition findProcessDefinitionByTaskId(String taskId) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        //获取流程定义id
        String processDefinitionId = task.getProcessDefinitionId();
        //查询流程定义的对象
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
        return processDefinition;
    }
    //查看当前活动,将坐标4个值存到map中
    @Override
    public Map<String, Object> findCoordingByTask(String taskId) {
        Map<String,Object>map=new HashMap<>();
        //获取任务id
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        //获取流程定义id
        String processDefinitionId = task.getProcessDefinitionId();
        //获取流程定义的实体对象
        ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinitionId);
        //获取流程实例id
        String processInstanceId = task.getProcessInstanceId();
        //使用实例id，查询正在执行的执行对象表
        ProcessInstance pi = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId).singleResult();
        //获取当前活动的id
        String activityId = pi.getActivityId();
        //
        ActivityImpl activity = processDefinitionEntity.findActivity(activityId);
        map.put("x",activity.getX());
        map.put("y",activity.getY());
        map.put("width",activity.getWidth());
        map.put("height",activity.getHeight());

        return map;
    }

    @Override
    public InputStream findImagInputStream(String deploymentId, String imageName) {
        return repositoryService.getResourceAsStream(deploymentId,imageName);
    }

    @Override
    public Task findTaskByBussinessKey(String bussiness_key) {
        Task task = this.taskService.createTaskQuery().processInstanceBusinessKey(bussiness_key).singleResult();
        return task;
    }

    @Override
    public List<Comment> findCommentListBillById(String bussiness_key) {
        HistoricProcessInstance hai=historyService.createHistoricProcessInstanceQuery().processInstanceBusinessKey(bussiness_key)
                .singleResult();
        return taskService.getProcessInstanceComments(hai.getId());
    }

    //强制删除
    @Override
    public void deleteDeploymentById(String deploymentId) {
        //有流程在工作就删除不成功
        // baoxiaoBillMapper.deleteByPrimaryKey(id);
        //强制删除
        repositoryService.deleteDeployment(deploymentId,true);
    }

    @Override
    public void deleteBaoxiaoBillById(String id) {
        baoxiaoBillMapper.deleteByPrimaryKey(Long.valueOf(id));
    }

}
